# -*- coding:utf-8 -*-
import ConfigParser
import re
import shutil
import threading
import time

import datetime

import os
import zipfile
from collections import OrderedDict

from com import DeviceHelper, LogUtil


class FlashTools:
    @classmethod
    def get_daily_zip(cls, root_dir, unzip_dir='./fastboot/', day_delta=1):
        # 先清空旧的版本
        if os.path.exists(unzip_dir):
            shutil.rmtree(unzip_dir)
        # 查找出昨天的版本路径
        yesterday = datetime.datetime.today() + datetime.timedelta(-1 * day_delta)
        yesterday_format = yesterday.strftime('%Y%m%d')[2:]
        # 先找到当天的文件夹
        pattern_dir = r'.*' + str(yesterday_format) + '.*[^SMT]_user_sign_efuse$'
        target_dir_list = FileUtils.search_for_dir(root_dir, pattern_dir)
        if len(target_dir_list) < 1 or target_dir_list is None:
            LogUtil.e('Could not find [' + yesterday_format + ']')
            return None
        # 在当天的文件夹中查找fastboot
        daily_dir = target_dir_list[0]
        zip_pattern = r'.*_fastboot.zip'
        fastboot_zip_list = FileUtils.search_for_dir(daily_dir, zip_pattern)
        if len(fastboot_zip_list) < 1 or fastboot_zip_list is None:
            LogUtil.e('Could not find fastboot.')
            return None
        # 解压
        zip_file = fastboot_zip_list[0]
        FileUtils.unzip(zip_file, unzip_dir)
        return unzip_dir + 'Tiffany_user_fastboot/'

    @classmethod
    def get_specify_rom(cls, root_dir, unzip_dir='./fastboot/'):
        # 先清空旧的版本
        if not os.path.exists(root_dir):
            LogUtil.e('Wrong rom dir path.')
            return None

        # 先清空旧的版本
        if os.path.exists(unzip_dir):
            shutil.rmtree(unzip_dir)

        # 在文件夹中查找fastboot
        zip_pattern = r'.*_fastboot.zip'
        fastboot_zip_list = FileUtils.search_for_dir(root_dir, zip_pattern)
        if len(fastboot_zip_list) < 1 or fastboot_zip_list is None:
            LogUtil.e('Could not found fastboot in ' + root_dir)
            return None
        # 解压
        zip_file = fastboot_zip_list[0]
        FileUtils.unzip(zip_file, unzip_dir)
        if root_dir.__contains__('_user_'):
            return unzip_dir + 'Tiffany_user_fastboot/'
        elif root_dir.__contains__('_userdebug_'):
            return unzip_dir + 'Tiffany_userdebug_fastboot/'

    @classmethod
    def __get_fastboot_bat(cls, fastboot_dir='./fastboot/Tiffany_user_fastboot/'):
        # 找到bat
        bat_pattern = r'fastboot_all.bat'
        bat_list = FileUtils.search_for_dir(fastboot_dir, bat_pattern)
        if len(bat_list) < 1 or bat_list is None:
            LogUtil.e('Could not found fastboot.bat')
            return None
        LogUtil.i('Found bat:' + bat_list[0])
        return bat_list[0]

    @classmethod
    def __get_fastboot_sh(cls, fastboot_dir='./fastboot/Tiffany_user_fastboot/'):
        # 找到bat
        sh_p = r'fastboot_all.sh'
        sh_list = FileUtils.search_for_dir(fastboot_dir, sh_p)
        if len(sh_list) < 1 or sh_list is None:
            LogUtil.e('Could not found fastboot.sh')
            return None
        LogUtil.i('Found sh:' + sh_list[0])
        return sh_list[0]

    @classmethod
    def __flash_dev(cls, root_dir, day_delta=1):
        has_new_rom = FlashTools.get_daily_zip(root_dir, day_delta=day_delta)
        if not has_new_rom:
            return False
        bat = FlashTools.get_fastboot_bat()
        # 初始工作目录
        ordir = os.getcwd()
        # bat文件所在的目录
        wdir = os.path.abspath(os.path.dirname(bat) + os.path.sep + ".")
        if bat is not None:
            new_bat = os.path.abspath(bat).replace('\\', '\\\\')
            LogUtil.i(new_bat)
            # 把工作目录切换到bat文件夹下
            os.chdir(wdir)
            LogUtil.i(os.getcwd())
            # 刷机
            flash_ok = FlashTools.exe_fastboot_bat(new_bat)
            # 切换回去
            os.chdir(ordir)
            LogUtil.i(os.getcwd())
            return flash_ok

        return False

    @classmethod
    def __exe_fastboot_bat(cls, script_file):
        import subprocess
        p = subprocess.Popen(script_file, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        returncode = p.poll()
        while returncode is None:
            line = p.stdout.readline()
            returncode = p.poll()
            line = line.strip()
            LogUtil.i(line)
            if 'Fastboot End' in line:
                p.terminate()
                LogUtil.i('Flash ok!')
                return True
        LogUtil.e('Flash failed.')
        return False

    @classmethod
    def flash_by_py(cls, dev_num, rom_dir, save_userdata=False):
        f_dict = OrderedDict()
        f_dict['xbl'] = 'xbl.elf'
        f_dict['tz'] = 'tz.mbn'
        f_dict['rpm'] = 'rpm.mbn'
        f_dict['hyp'] = 'hyp.mbn'
        f_dict['pmic'] = 'pmic.elf'
        f_dict['boot'] = 'boot.img'
        f_dict['recovery'] = 'recovery.img'
        f_dict['system'] = 'system.img'
        f_dict['keymaster'] = 'keymaster64.mbn'
        f_dict['cmnlib'] = 'cmnlib.mbn'
        f_dict['cmnlib64'] = 'cmnlib64.mbn'
        f_dict['mdtpsecapp'] = 'mdtpsecapp.mbn'
        f_dict['mdtp'] = 'mdtp.img'
        f_dict['modem'] = 'NON-HLOS.bin'
        f_dict['dsp'] = 'dspso.bin'
        f_dict['abl'] = 'abl.elf'
        f_dict['bluetooth'] = 'BTFM.bin'
        f_dict['persist'] = 'persist.img'
        f_dict['devcfg'] = 'devcfg.mbn'
        f_dict['storsec'] = 'storsec.mbn'
        if not save_userdata:
            f_dict['userdata'] = 'userdata.img'
        f_dict['vendor'] = 'vendor.img'
        f_dict['cache'] = 'cache.img'
        f_dict['splash'] = 'splash.img'

        # 检查条件是否具备
        LogUtil.i(os.getcwd())
        for key in f_dict.iterkeys():
            my_file = rom_dir + f_dict[key]
            if not os.path.exists(my_file):
                LogUtil.e(my_file + ' File not exist!')
                del f_dict[key]

        # 判断设备是否连接
        mdev = DeviceHelper(dev_num)
        mdev.wait_device_ready()
        # 如果文件都存在，则开始刷机
        os.system('adb -s ' + dev_num + ' reboot bootloader')
        os.system('fastboot -s ' + dev_num + ' devices')
        for key in f_dict.iterkeys():
            my_file = rom_dir + f_dict[key]
            cmd = 'fastboot -s ' + dev_num + ' flash ' + key + ' ' + my_file
            LogUtil.i(cmd)
            os.system(cmd)
        os.system('fastboot -s ' + dev_num + ' reboot')
        return True


class FileUtils:
    '''获取文件的大小,结果保留两位小数，单位为MB'''

    @classmethod
    def get_size(cls, file_path, size=0):
        for root, dirs, files in os.walk(file_path):
            for f in files:
                size += os.path.getsize(os.path.join(root, f))
        return size

    @classmethod
    def search_for_dir(cls, root_dir, pattern):
        targetList = []
        for mdir in os.listdir(root_dir):
            isMatch = re.match(pattern, mdir, re.M | re.I)
            fullPath = os.path.join(root_dir, mdir)
            if isMatch:
                LogUtil.i('Target found:' + fullPath)
                targetList.append(fullPath)
        return targetList

    @classmethod
    def search_for_file(cls, root_dir, pattern, file_list):
        for mfile in os.listdir(root_dir):
            path = os.path.join(root_dir, mfile)
            if os.path.isfile(path):
                is_match = re.match(pattern, path, re.M | re.I)
                if is_match:
                    LogUtil.i('Target found:' + path)
                    file_list.append(path)
            else:
                FileUtils.search_for_file(path, pattern, file_list)

    @classmethod
    def get_latest_file(cls, full_list):
        if len(full_list) < 1:
            return None
        t = os.path.getctime(full_list[0])
        latest_file = full_list[0]
        for f in full_list:
            temp = os.path.getctime(f)
            if temp > t:
                latest_file = f
        return latest_file

    @classmethod
    def unzip(cls, zip_file, unzip_dir):
        r = zipfile.is_zipfile(zip_file)
        if r:
            starttime = time.time()
            fz = zipfile.ZipFile(zip_file, 'r')
            for file in fz.namelist():
                LogUtil.i(file)
                fz.extract(file, unzip_dir)
            endtime = time.time()
            times = endtime - starttime
        else:
            LogUtil.e(zip_file + ' is not zip file')
        LogUtil.i('Unzip done. Taked time: ' + str(times))


class specify_rom_task(threading.Thread):  # 继承父类threading.Thread
    def __init__(self, dev_num, local_rom, save_userdata):
        threading.Thread.__init__(self)
        self.dev_num = dev_num
        self.local_rom = local_rom
        self.save_userdata = save_userdata

    def run(self):
        flash_ok = FlashTools.flash_by_py(self.dev_num, self.local_rom, self.save_userdata)
        if flash_ok:
            LogUtil.i(self.dev_num + ' All done.')
        else:
            LogUtil.i(self.dev_num + ' Failed.')


if __name__ == '__main__':
    scf = ConfigParser.SafeConfigParser()
    scf.read('data.conf')
    temp = scf.get('Tiffany', 'dev_list')
    dev_list = temp.split(',')
    rom_dir = scf.get('Tiffany', 'rom_dir')
    save_userdata = scf.get('Tiffany', 'save_userdata')
    if save_userdata.__contains__('True'):
        save_userdata = True
    else:
        save_userdata = False
    LogUtil.i('dev_lis:' + str(dev_list))
    LogUtil.i('rom:' + rom_dir)
    LogUtil.i('save userdata:' + str(save_userdata))

    # 获取指定版本
    local_dir = FlashTools.get_specify_rom(rom_dir, unzip_dir='./specified_rom/')
    # local_dir='./specified_rom/Tiffany_user_fastboot/'
    # 获取从
    if local_dir is None:
        LogUtil.e('flash mission abortted!')
        exit()
    for dev_num in dev_list:
        t = specify_rom_task(dev_num, local_dir, save_userdata=save_userdata)
        t.start()
    raw_input("Press enter to close.")
